package com.psy.counseling.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.psy.counseling.entity.*;
import com.psy.counseling.mapper.FirstVisitMapper;
import com.psy.counseling.mapper.UserMapper;
import com.psy.counseling.service.FirstVisitService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.psy.counseling.service.MailService;
import com.psy.counseling.service.TypeService;
import com.psy.counseling.service.UserService;
import com.psy.counseling.utils.Result;
import com.psy.counseling.utils.TimeUtil;
import com.psy.counseling.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 梁学儒
 * @since 2022-05-31
 */
@Service
@Slf4j
public class FirstVisitServiceImpl extends ServiceImpl<FirstVisitMapper, FirstVisit> implements FirstVisitService {
    @Resource
    private FirstVisitMapper firstVisitMapper;

    @Resource
    private MailService mailService;

    @Resource
    private UserService userService;

    @Resource
    private UserMapper userMapper;

    @Resource
    private TypeService typeService;

    @Resource
    private ScheduleServiceImpl scheduleService;

    private final String SUBJECT = "来自心理社区的提醒邮件";

    private final String[] checkType = {"审核中","审核未通过","审核通过","撤销申请"};

    private final String[] conclusion = {"无需咨询","安排咨询","转介送诊"};

    private final String[] type = {"人际交往","情绪心理","情爱心理","心理健康","学习心理","个性心理","性心理"};

    private final String[] level = {"高","中","低"};

    /**
     * 添加初访
     * @param firstVisit
     * @return ResultVo
     */
    @Transactional
    public ResultVo addFirstVisit(FirstVisit firstVisit){
        if(ObjectUtils.isEmpty(firstVisit.getVisitorId())||ObjectUtils.isEmpty(firstVisit.getStudentId())){
            return ResultVo.builder().code("400").msg("插入失败!").data("用户不能为空").build();
        }else if(ObjectUtils.isEmpty(firstVisit.getStartTime())||ObjectUtils.isEmpty(firstVisit.getEndTime())){
            return ResultVo.builder().code("400").msg("插入失败!").data("时间不能为空").build();
        }else if(ObjectUtils.isEmpty(firstVisit.getScore())){
            return ResultVo.builder().code("400").msg("插入失败!").data("分数不能为空").build();
        }else {
            firstVisit.setPlace("心理咨询室");
            firstVisit.setCheckState(checkType[0]);
            Date currentDate = new Date();
            int i = TimeUtil.getDayWeekOfDate(TimeUtil.timeToStr(currentDate));
            firstVisit.setDay(i);
            log.info(String.valueOf(i));
            if(firstVisitMapper.insert(firstVisit)>=1){
                return ResultVo.builder().code("200").msg("插入成功！").data(firstVisit).build();
            }
            else {
                return ResultVo.builder().code("500").msg("插入失败！").data("系统错误").build();
            }
        }
    }

    /**
     * 删除初访
     * @param deleteVO
     * @return ResultVo
     */
    @Transactional
    public ResultVo deleteFirstVisit(DeleteVO deleteVO){
        if(ObjectUtils.isNotEmpty(deleteVO.getId())){
            if(this.removeById(deleteVO.getId())){
                return ResultVo.builder().code("200").msg("删除成功！").data(null).build();
            }
        }else if(ObjectUtils.isNotEmpty(deleteVO.getIds())){
            if(this.removeByIds(deleteVO.getIds())){
                return ResultVo.builder().code("200").msg("删除成功！").data(null).build();
            }
        }else {
            return ResultVo.builder().code("400").msg("删除失败！").data("id不能为空").build();
        }
        return ResultVo.builder().code("500").msg("删除失败！").data("系统错误").build();
    }

    /**
     * 查询初访
     * @param firstVisit
     * @param page
     * @return ResultVo
     */
    @Transactional
    public ResultVo listFirstVisits(FirstVisit firstVisit, PageVO page) {
        Page<FirstVisit> firstVisitPage = new Page<>(page.getPageNum(),page.getPageSize());
        LambdaQueryWrapper<FirstVisit> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ObjectUtils.isNotEmpty(firstVisit.getDay()),FirstVisit::getDay,firstVisit.getDay())
                .eq(ObjectUtils.isNotEmpty(firstVisit.getVisitorId()),FirstVisit::getVisitorId,firstVisit.getVisitorId())
                .eq(ObjectUtils.isNotEmpty(firstVisit.getStudentId()),FirstVisit::getStudentId,firstVisit.getStudentId())
                .eq(ObjectUtils.isNotEmpty(firstVisit.getCheckState()),FirstVisit::getCheckState,firstVisit.getCheckState())
                .eq(ObjectUtils.isNotEmpty(firstVisit.getId()),FirstVisit::getId,firstVisit.getId());
        firstVisitPage = this.page(firstVisitPage,queryWrapper);
        Page<FirstVisitVo> firstVisitVoPage = new Page<>();
        BeanUtils.copyProperties(firstVisitPage,firstVisitVoPage);
        List<FirstVisitVo> list = new ArrayList<>();
        for(int i = 0;i<firstVisitPage.getRecords().size();i++){
            FirstVisitVo firstVisitVo = new FirstVisitVo();
            BeanUtils.copyProperties(firstVisitPage.getRecords().get(i),firstVisitVo);
            firstVisitVo.setVisitor(userService.getById(firstVisitPage.getRecords().get(i).getVisitorId()).getRealName());
            firstVisitVo.setStudent(userService.getById(firstVisitPage.getRecords().get(i).getStudentId()).getUsername());
            list.add(firstVisitVo);
        }
        firstVisitVoPage.setRecords(list);
        return ResultVo.builder().code("200").msg("查询成功！").data(firstVisitVoPage).build();
    }

    /**
     * 修改初访
     * @param firstVisit
     * @return ResultVo
     */
    @Transactional
    public ResultVo updateFirstVisit(FirstVisit firstVisit){
        if(ObjectUtils.isNotEmpty(firstVisit.getId())){
            QueryWrapper<FirstVisit> wrapper = new QueryWrapper<>();
            wrapper.eq("id",firstVisit.getId());
            FirstVisit firstVisit1 = firstVisitMapper.selectById(firstVisit.getId());
            if(ObjectUtils.isNotEmpty(firstVisit.getStartTime())){
                firstVisit1.setStartTime(firstVisit.getStartTime());
                firstVisit1.setDay(TimeUtil.getDayWeekOfDate(firstVisit.getStartTime()));
            }if(ObjectUtils.isNotEmpty(firstVisit.getEndTime())){
                firstVisit1.setEndTime(firstVisit.getEndTime());
            }if(ObjectUtils.isNotEmpty(firstVisit.getLevel())){
                firstVisit1.setLevel(firstVisit.getLevel());
            }if(ObjectUtils.isNotEmpty(firstVisit.getConclusion())){
                firstVisit1.setConclusion(firstVisit.getConclusion());
            }if(ObjectUtils.isNotEmpty(firstVisit.getType())){
                firstVisit1.setType(firstVisit.getType());
            }
            if(this.update(firstVisit1,wrapper)){
                return ResultVo.builder().code("200").msg("修改成功！").data(firstVisit1).build();
            }else {
                return ResultVo.builder().code("500").msg("修改失败！").data("系统错误").build();
            }
        }else {
            return ResultVo.builder().code("400").msg("修改失败！").data("初访id不能为空").build();
        }
    }

    /**
     * 通过初访
     * @param firstVisit
     * @return ResultVo
     */
    @Transactional
    public ResultVo agreeFirstVisit(FirstVisit firstVisit){
        // 用于记录该初访时间段，初访员是否值班
        Boolean flag = false;
        if(ObjectUtils.isNotEmpty(firstVisit)&&ObjectUtils.isNotEmpty(firstVisit.getVisitorId())
                &&ObjectUtils.isNotEmpty(firstVisit.getStartTime())&&ObjectUtils.isNotEmpty(firstVisit.getEndTime())) {
            Integer dayWeek = TimeUtil.getDayWeekOfDate(firstVisit.getStartTime());
            //获取初访员周几的值班安排
            LambdaQueryWrapper<Schedule> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Schedule::getDay, dayWeek)
                    .eq(Schedule::getUseId, firstVisit.getVisitorId())
                    .orderByDesc(Schedule::getStart);
            List<Schedule> schedules = scheduleService.list(wrapper);
            String aSTime = TimeUtil.getTime(firstVisit.getStartTime());
            String aETime = TimeUtil.getTime(firstVisit.getEndTime());
            String sTime = null;
            String eTime = null;
            for (Schedule s : schedules) {
                if (aSTime.compareTo(s.getStart()) >= 0 && aETime.compareTo(s.getEnd()) <= 0) {
                    sTime = s.getStart();
                    eTime = s.getEnd();
                    flag = true;
                    break;
                }
            }
            //如果初访员该时间段值班
            if (flag) {
                // 查询该初访员在该时间段是否有初访
                LambdaQueryWrapper<FirstVisit> firstVisitLambdaQueryWrapper = new LambdaQueryWrapper<>();
                firstVisitLambdaQueryWrapper.eq(FirstVisit::getVisitorId, firstVisit.getVisitorId())
                        .eq(FirstVisit::getCheckState, checkType[2]) //审核通过
                        .ge(FirstVisit::getStartTime, TimeUtil.formatHhMmSsOfDate(firstVisit.getStartTime(), true))
                        .lt(FirstVisit::getEndTime, TimeUtil.formatHhMmSsOfDate(firstVisit.getStartTime(), false))
                        .orderByDesc(FirstVisit::getStartTime);

                List<FirstVisit> firstVisits = this.list(firstVisitLambdaQueryWrapper);
                String askStartTime = firstVisit.getStartTime();
                String askEndTime = firstVisit.getEndTime();
                for (FirstVisit f : firstVisits) {
                    if ((askStartTime.compareTo(f.getStartTime()) <= 0 && askEndTime.compareTo(f.getEndTime()) >= 0)
                            || (askStartTime.compareTo(f.getStartTime()) >= 0 && askStartTime.compareTo(f.getEndTime()) < 0)
                            || (firstVisit.getEndTime().compareTo(f.getStartTime()) > 0 && firstVisit.getEndTime().compareTo(f.getEndTime()) <= 0)) {
                        firstVisit.setCheckState(checkType[1]);
                        this.updateById(firstVisit);
                        sendMsg(firstVisit.getId(), false);
                        return ResultVo.builder().code("200").msg("审核未通过").data("此初访员该时段已经被预约").build();
                    }
                }
                firstVisit.setCheckState(checkType[2]);
                this.updateById(firstVisit);
                sendMsg(firstVisit.getId(), true);
                return ResultVo.builder().code("200").msg("审核通过").data(firstVisit).build();
            }else {
                firstVisit.setCheckState(checkType[1]);
                this.updateById(firstVisit);
                sendMsg(firstVisit.getId(), true);
                return ResultVo.builder().code("200").msg("审核未通过").data("此初访员该时段未值班").build();
            }
        }
        return ResultVo.builder().code("400").msg("初访信息不完全").data(null).build();
    }

    /**
     * 驳回初访
     * @param id
     * @return ResultVo
     */
    @Transactional
    public ResultVo opposeFirstVisit(Long id){
        if(ObjectUtils.isNotEmpty(id)){
            LambdaUpdateWrapper<FirstVisit> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(FirstVisit::getId,id).set(FirstVisit::getCheckState,checkType[1]);
            this.update(wrapper);
            return ResultVo.builder().code("200").msg("初访预约驳回成功").data(wrapper).build();
        }
        return ResultVo.builder().code("400").msg("初访预约驳回失败").data(null).build();
    }

    /**
     * 撤销初访
     * @param id
     * @return ResultVo
     */
    @Transactional
    public ResultVo cancelFirstVisit(Long id){
        if(ObjectUtils.isNotEmpty(id)){
            Date now = new Date();
            FirstVisit firstVisit = this.getById(id);
            String startTime = TimeUtil.timeOperation(firstVisit.getStartTime(), 24L * 60, false);
            Date start = TimeUtil.strToDateTime(startTime);
            if(now.before(start)){
                firstVisit.setCheckState(checkType[3]);
                this.save(firstVisit);
                return ResultVo.builder().code("200").msg("初访预约撤销成功").data(null).build();
            }
        }
        return ResultVo.builder().code("400").msg("初访预约撤销失败").data("请提前至少一天撤销").build();
    }

    /**
     * 通过初访id向学生邮箱发送初访预约详情
     * @param id
     * @param through
     */
    public void sendMsg(Long id,boolean through){
        FirstVisit firstVisit = firstVisitMapper.selectById(id);
        User student = userService.getById(firstVisit.getStudentId());
        User visitor = userService.getById(firstVisit.getVisitorId());
        if (ObjectUtils.isNotEmpty(student.getEmail())){
            //发送邮箱
            String content = null;
            if(through){
                content = "亲爱的"+student.getRealName()+"同学,"+"您预约"+visitor.getRealName()+"老师的初访"+firstVisit.getStartTime()+"~"+firstVisit.getEndTime()+"时段预约成功，请准时初访！";
            }else{
                content = "亲爱的"+student.getRealName()+"同学,"+"您预约"+visitor.getRealName()+"老师的初访"+firstVisit.getStartTime()+"~"+firstVisit.getEndTime()+"时段预约失败，请重新预约！";
            }
            mailService.sendMimeMail(student.getEmail(),SUBJECT,content);
        }
    }

    /**
     * 获取审核通过后的初访状态
     * @param id
     * @return ResultVo
     */
    @Transactional
    public ResultVo getStatus(Long id) {
        if(ObjectUtils.isEmpty(id)){
            return ResultVo.builder().code("400").msg("初访id不能为空！").data(null).build();
        }
        Date now = new Date();
        FirstVisit firstVisit = this.getById(id);
        Date startTime = TimeUtil.strToDateTime(firstVisit.getStartTime());
        Date endTime = TimeUtil.strToDateTime(firstVisit.getEndTime());
        if(now.before(startTime)){
            return ResultVo.builder().code("200").msg("初访未开始").data(null).build();
        }
        if(now.before(endTime)&&now.after(startTime)){
            return ResultVo.builder().code("200").msg("初访进行中").data(null).build();
        }
        return ResultVo.builder().code("200").msg("初访已结束").data(null).build();
    }

    /**
     * 返回结论、类型
     * @param
     * @return ResultVo
     */
    @Transactional
    public ResultVo getConclusion(){
        QueryWrapper<Type> wrapper = new QueryWrapper<>();
        wrapper.eq("type_info","初访结论");
        return ResultVo.builder().code("200").msg("查询成功!").data(typeService.list(wrapper)).build();
    }

    @Transactional
    public ResultVo getVisitType(){
        QueryWrapper<Type> wrapper = new QueryWrapper<>();
        wrapper.eq("type_info","问题类型");
        return ResultVo.builder().code("200").msg("查询成功!").data(typeService.list(wrapper)).build();
    }

}
